package com.zeyun.EasyOnlineShareCloud.controller;

import cn.dev33.satoken.annotation.SaCheckLogin;
import cn.dev33.satoken.annotation.SaCheckRole;
import cn.dev33.satoken.util.SaResult;
import cn.hutool.core.util.StrUtil;
import com.zeyun.EasyOnlineShareCloud.common.convention.exception.ServiceException;
import com.zeyun.EasyOnlineShareCloud.service.FileService;
import lombok.RequiredArgsConstructor;
import org.springframework.core.io.InputStreamResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;

/**
 * 文件控制器
 */
@RestController
@RequestMapping("/v1/file")
@RequiredArgsConstructor
public class FileController {

	private final FileService fileService;

	/**
	 * 上传文件
	 */
	@PostMapping("/upload")
	@SaCheckLogin
	public SaResult uploadFile(MultipartFile file, String subPath, String specialPrefix,
							   @RequestHeader(value = "ClientIP", required = false) String IP) {
		// 如果IP为空则设置为0.0.0.0
		if (StrUtil.isBlank(IP)) IP = "0.0.0.0";
		return SaResult.data(fileService.upload(file, subPath, specialPrefix, IP));
	}

	/**
	 * 下载文件（通过访问码）
	 */
	@GetMapping("/download")
	public ResponseEntity<?> download(@RequestParam(value = "id", required = false) String fileId,
									  @RequestParam(value = "code") String access_code,
									  @RequestHeader(value = "ClientIP", required = false) String IP) {
		if (access_code.length() != 4) {
			throw new ServiceException("异常访问码错误");
		}
		if (StrUtil.isBlank(IP)) IP = "0.0.0.0";
		access_code = access_code.toUpperCase();
		try {
			// 获取文件信息和输入流
			Map<String, Object> fileInfo = fileService.download(access_code, fileId, IP);
			InputStreamResource resource = (InputStreamResource) fileInfo.get("resource");
			String fileName = (String) fileInfo.get("fileName");
			long fileSize = (long) fileInfo.get("fileSize");
			String contentType = (String) fileInfo.get("contentType");

			// 设置响应头
			HttpHeaders headers = new HttpHeaders();
			headers.setContentType(MediaType.parseMediaType(contentType));
			headers.setContentLength(fileSize);
			headers.set(HttpHeaders.CONTENT_TYPE, "application/octet-stream;charset=utf-8");
			headers.set(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + URLEncoder.encode(fileName,
					StandardCharsets.UTF_8) + "\"");

			// 设置响应头
			return ResponseEntity.ok()
					.contentType(MediaType.parseMediaType(contentType))
					.contentLength(fileSize)
					// 设置utf8
					.headers(headers)
					.body(resource);
		} catch (ServiceException e) {
			// 关键修改：明确设置Content-Type为application/json，并返回SaResult对象
			HttpHeaders headers = new HttpHeaders();
			headers.setContentType(MediaType.APPLICATION_JSON);
			return new ResponseEntity<>(SaResult.error(e.getMessage()), headers, HttpStatus.OK);
		} catch (Exception e) {
			// 捕获通用异常，同样返回JSON格式
			HttpHeaders headers = new HttpHeaders();
			headers.setContentType(MediaType.APPLICATION_JSON);
			return new ResponseEntity<>(SaResult.error("服务器内部错误：" + e.getMessage()), headers,
					HttpStatus.INTERNAL_SERVER_ERROR);
		}
	}

	@GetMapping("/valid-access-code")
	@SaCheckLogin
	public SaResult validAccessCode(@RequestParam(value = "code") String access_code) {
		if (access_code.length() != 4) {
			throw new ServiceException("异常访问码错误");
		}
		fileService.validAccessCode(access_code);
		return SaResult.ok("访问码验证成功!");
	}

	/**
	 * 获取压缩包内容
	 */
	@GetMapping("/archive-contents")
	@SaCheckLogin
	public SaResult getArchiveContents(@RequestParam(value = "id") String fileId,
									   @RequestParam(value = "code") String accessCode) {
		if (accessCode.length() != 4) {
			throw new ServiceException("异常访问码错误");
		}
		try {
			// 转换为大写
			accessCode = accessCode.toUpperCase();
			// 获取压缩包内容
			List<Map<String, Object>> contents = fileService.getArchiveContents(accessCode, fileId);
			return SaResult.data(contents);
		} catch (ServiceException e) {
			return SaResult.error(e.getMessage());
		} catch (Exception e) {
			return SaResult.error("获取压缩包内容失败: " + e.getMessage());
		}
	}

	/**
	 * 预览文件（不计入下载次数）
	 */
	@GetMapping("/preview")
	@SaCheckRole("admin")
	public ResponseEntity<?> preview(@RequestParam(value = "id", required = false) String fileId,
							@RequestParam(value = "code") String access_code,
							@RequestHeader(value = "ClientIP", required = false) String IP) {
		if (access_code.length() != 4) {
			throw new ServiceException("异常访问码错误");
		}
		if (StrUtil.isBlank(IP)) IP = "0.0.0.0";
		access_code = access_code.toUpperCase();
		try {
			// 获取文件信息和输入流，使用预览模式（不计入下载次数）
			Map<String, Object> fileInfo = fileService.preview(access_code, fileId, IP);
			InputStreamResource resource = (InputStreamResource) fileInfo.get("resource");
			String fileName = (String) fileInfo.get("fileName");
			long fileSize = (long) fileInfo.get("fileSize");
			String contentType = (String) fileInfo.get("contentType");

			// 设置响应头
			HttpHeaders headers = new HttpHeaders();
			headers.setContentType(MediaType.parseMediaType(contentType));
			headers.setContentLength(fileSize);
			
			// 对于PDF文件，设置为内联显示而不是下载
			if (contentType.equals("application/pdf")) {
				headers.set(HttpHeaders.CONTENT_DISPOSITION, "inline; filename=\"" + URLEncoder.encode(fileName,
						StandardCharsets.UTF_8) + "\"");
			} else {
				// 其他文件类型使用标准的内容类型
				headers.set(HttpHeaders.CONTENT_TYPE, contentType);
				headers.set(HttpHeaders.CONTENT_DISPOSITION, "inline; filename=\"" + URLEncoder.encode(fileName,
						StandardCharsets.UTF_8) + "\"");
			}

			// 返回响应
			return ResponseEntity.ok()
					.contentType(MediaType.parseMediaType(contentType))
					.contentLength(fileSize)
					.headers(headers)
					.body(resource);
		} catch (ServiceException e) {
			// 设置Content-Type为application/json，并返回SaResult对象
			HttpHeaders headers = new HttpHeaders();
			headers.setContentType(MediaType.APPLICATION_JSON);
			return new ResponseEntity<>(SaResult.error(e.getMessage()), headers, HttpStatus.OK);
		} catch (Exception e) {
			// 捕获通用异常，同样返回JSON格式
			HttpHeaders headers = new HttpHeaders();
			headers.setContentType(MediaType.APPLICATION_JSON);
			return new ResponseEntity<>(SaResult.error("服务器内部错误：" + e.getMessage()), headers,
					HttpStatus.INTERNAL_SERVER_ERROR);
		}
	}
}